package tiandang.core.service.impl;

import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import tiandang.core.config.AuthResource;
import tiandang.core.dao.*;
import tiandang.core.error.BusinessException;
import tiandang.core.error.EmBusinessError;
import tiandang.core.model.*;
import tiandang.core.service.WXService;
import tiandang.core.utils.Constant;
import tiandang.core.utils.HttpClientUtil;
import tiandang.core.utils.JsonUtils;
import tiandang.core.utils.WX_TemplateMsgUtil;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class WXServiceImpl implements WXService {

  private final Logger log = LoggerFactory.getLogger(this.getClass());

  @Autowired
  private AuthResource resource;

  @Autowired
  private WXTokenMapper wxTokenMapper;

  @Autowired
  private WXFormidMapper wxFormidMapper;

  @Autowired
  private PromoMapper promoMapper;

  @Autowired
  private PromoProductMapper promoProductMapper;

  @Autowired
  private ManagerMapper managerMapper;

  @Autowired
  private PromoManagerMapper promoManagerMapper;


  //为什么把accessToken保存在数据库呢,因为前后端服务都有可能调用,保存在两个服务内存中无法重复利用
  @Override
  public String getAccessToken() {

    //先从数据库查询
    WXToken wxToken = wxTokenMapper.getWXToken();
    if (wxToken == null) {
      return getAccessTokenFromWX(false);
    }

    Long now = new Date().getTime() / 1000;
    Long updatetime = wxToken.getUpdatetime().getTime() / 1000;

    if (now - updatetime > wxToken.getExpires()) {
      return getAccessTokenFromWX(true);
    } else {
      return wxToken.getAccessToken();
    }

  }

  @Override
  public WXFormid getFormidByOpenid(String openid) {
    return wxFormidMapper.getFormidByOpenid(openid);
  }

  @Override
  public void deleteFormid(String formid) {
    wxFormidMapper.deleteByPrimaryKey(formid);
  }

  @Override
  public void saveFormid(WXFormid formid) {
    wxFormidMapper.insertSelective(formid);
  }

  public String getAccessTokenFromWX(Boolean isExist) {
    AuthResource bean = new AuthResource();
    BeanUtils.copyProperties(resource, bean);

    Map<String, String> param = new HashMap<>();
    param.put("grant_type", "client_credential");
    param.put("appid", bean.getAppid());
    param.put("secret", bean.getSecret());

    String wxResult = HttpClientUtil.doGet(Constant.WECHAT_API_TOKEN, param);
    log.info("从微信获取access_token wxResult: {}", wxResult);

    WXTokenModel wxTokenModel = JsonUtils.jsonToPojo(wxResult, WXTokenModel.class);
    if (!StringUtils.isEmpty(wxTokenModel.getAccess_token())) {
      //把获取的新的access_token更新到数据库
      WXToken wxToken = new WXToken();
      wxToken.setAccessToken(wxTokenModel.getAccess_token());
      wxToken.setExpires(wxTokenModel.getExpires_in());
      if (isExist) {
        wxTokenMapper.updateAccessToken(wxToken);
      } else {
        wxTokenMapper.insertSelective(wxToken);
      }
      return wxTokenModel.getAccess_token();
    }

    return null;
  }

//  https://developers.weixin.qq.com/miniprogram/dev/api-backend/templateMessage.send.html

  @Override
  @Async
  public void pushMessage(Integer promoId) throws BusinessException {
    Promo promo = promoMapper.selectByPrimaryKey(promoId);
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    String start = dateFormat.format(new Date(promo.getStartTimestamp()));
    String end = dateFormat.format(new Date(promo.getEndTimestamp()));

    Long hour = (promo.getEndTimestamp() - new Date().getTime()) / (1000 * 60 * 60);
    Long totalMinutes = (promo.getEndTimestamp() - new Date().getTime()) % (1000 * 60);
    Long minutes = totalMinutes % 60;
    String time = hour + "小时" + minutes + "分";

    List<PromoProduct> promoProductList = promoProductMapper.getListByPromoId(promoId);
    String productName = promoProductList.get(0).getName();
    BigDecimal price = promoProductList.get(0).getPresentPrice();

    //查出本次开团的团长,再从fromid表里筛选 2019-05-23
    List<PromoManager> promoManagerList = promoManagerMapper.getListByPromoId(promoId);
    List<Integer> managerIdList = new ArrayList<>();
    for(PromoManager promoManager : promoManagerList){
      managerIdList.add(promoManager.getManagerId());
    }

    //查询wx_formid表,以openid去重,然后循环推送
    List<WXFormid> wxFormidList = wxFormidMapper.getListNoRepeatOpenid(managerIdList);
    if (wxFormidList == null || wxFormidList.size() == 0) {
      throw new BusinessException(EmBusinessError.FORMID_NOT_ENOUGH);
    }

    AuthResource bean = new AuthResource();
    BeanUtils.copyProperties(resource, bean);
    String templateId = bean.getTemplateId();

    String accessToken = getAccessToken();
    String emphasisKeyword = "keyword1.DATA";

    String page = "pages/detail/detail?promoId=" + promoId + "&managerId=";
    for (WXFormid wxFormid : wxFormidList) {
      Manager manager = managerMapper.selectByPrimaryKey(wxFormid.getManagerId());
      Map<String, TemplateData> param = new HashMap<>();
      param.put("keyword1", new TemplateData(manager.getName() + "的团购"));
      param.put("keyword2", new TemplateData(productName));
      param.put("keyword3", new TemplateData(price.toString()));
      param.put("keyword4", new TemplateData(manager.getName()));
      param.put("keyword5", new TemplateData(start));
      param.put("keyword6", new TemplateData(end));
      param.put("keyword7", new TemplateData(time));

      JSONObject jsonObject = JSONObject.fromObject(param);

      String result = WX_TemplateMsgUtil.sendWechatMsgToUser(wxFormid.getOpenid(), templateId, page + wxFormid.getManagerId(), wxFormid.getFormId(), jsonObject, emphasisKeyword, accessToken);
      if (result.equals("success")) {
//        //用过之后删除
        deleteFormid(wxFormid.getFormId());
      }
    }

    promoMapper.updatePushStatus(promoId);
  }

}
